/*
 * Copyright (C) 2010  Paulo Cesar Pereira de Andrade.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#ifndef _elightning_h
#define _elightning_h

#include "etypes.h"

/*
 * Types
 */
enum elit_code {
    elit_label,
    elit_movr_i,
    elit_movr_l,
    elit_movi_i,
    elit_movi_l,
    elit_movi_p,
    elit_movi_f,
    elit_movi_d,
    elit_negr_i,
    elit_negr_l,
    elit_negr_f,
    elit_negr_d,
    elit_notr_i,
    elit_notr_l,
    elit_absr_f,
    elit_absr_d,
    elit_extr_i_f,
    elit_extr_i_d,
    elit_extr_l_f,
    elit_extr_l_d,
    elit_extr_f_d,
    elit_extr_d_f,
    elit_floorr_f_i,
    elit_floorr_f_l,
    elit_floorr_d_i,
    elit_floorr_d_l,
    elit_truncr_f_i,
    elit_truncr_f_l,
    elit_truncr_d_i,
    elit_truncr_d_l,
    elit_ldi_p,
    elit_ldxi_c,
    elit_ldxi_uc,
    elit_ldxi_s,
    elit_ldxi_us,
    elit_ldxi_i,
    elit_ldxi_ui,
    elit_ldxi_l,
    elit_ldxi_ul,
    elit_ldxi_p,
    elit_ldxi_f,
    elit_ldxi_d,
    elit_stxi_c,
    elit_stxi_s,
    elit_stxi_i,
    elit_stxi_l,
    elit_stxi_p,
    elit_stxi_f,
    elit_stxi_d,
    elit_addr_i,
    elit_addr_ui,
    elit_addr_l,
    elit_addr_f,
    elit_addr_d,
    elit_addi_i,
    elit_addi_l,
    elit_addi_p,
    elit_addcr_ui,
    elit_addxr_ui,
    elit_addci_ui,
    elit_addxi_ui,
    elit_subr_i,
    elit_subr_ui,
    elit_subr_l,
    elit_subr_f,
    elit_subr_d,
    elit_subi_i,
    elit_subi_l,
    elit_subi_p,
    elit_subcr_ui,
    elit_subxr_ui,
    elit_subci_ui,
    elit_subxi_ui,
    elit_mulr_f,
    elit_mulr_d,
    elit_divr_f,
    elit_divr_d,
    elit_rshi_i,
    elit_ner_i,
    elit_ner_l,
    elit_ner_d,
    elit_nei_i,
    elit_nei_l,
    elit_ltr_i,
    elit_ltr_ui,
    elit_ltr_l,
    elit_ltr_d,
    elit_lti_i,
    elit_lti_l,
    elit_ler_i,
    elit_ler_ui,
    elit_ler_l,
    elit_ler_d,
    elit_lei_i,
    elit_lei_l,
    elit_eqr_i,
    elit_eqr_l,
    elit_eqr_d,
    elit_eqi_i,
    elit_eqi_l,
    elit_ger_i,
    elit_ger_ui,
    elit_ger_l,
    elit_ger_d,
    elit_gei_i,
    elit_gei_l,
    elit_gtr_i,
    elit_gtr_ui,
    elit_gtr_l,
    elit_gtr_d,
    elit_gti_i,
    elit_gti_l,
    elit_blti_i,
    elit_blei_i,
    elit_beqi_i,
    elit_bgei_i,
    elit_bgti_i,
    elit_bnei_i,
    elit_blti_l,
    elit_blei_l,
    elit_beqi_l,
    elit_bgei_l,
    elit_bgti_l,
    elit_bnei_l,
    elit_bger_f,
    elit_bger_d,
    elit_boaddr_i,
    elit_boaddr_l,
    elit_boaddi_i,
    elit_boaddi_ui,
    elit_boaddi_l,
    elit_boaddi_ul,
    elit_bosubr_i,
    elit_bosubr_l,
    elit_bosubi_i,
    elit_bosubi_ui,
    elit_bosubi_l,
    elit_jmpi,
    elit_calli,
    elit_prepare,
    elit_pusharg_i,
    elit_pusharg_l,
    elit_pusharg_p,
    elit_finish,
};

struct elit_node {
    elit_node_t		*next;
    elit_code_t		 code;
    int			 r0;
    int			 r1;
    int			 r2;
    union {
	int		 i;
	long		 l;
	void		*p;
	float		 f;
	double		 d;
	elit_node_t	*node;
    } i0;
    union {
	int		 i;
	long		 l;
	void		*p;
	float		 f;
	double		 d;
    } i1;
    elit_node_t		*link;
};

struct ecase {
    eint_t	 value;
    elabel_t	*label;
};

struct evswitch {
    eint_t	 imin;
    eint_t	 imax;
    eint32_t	 mask;
    elabel_t	*cases[1];
};

struct ehswitch {
    eint_t	 imin;
    eint_t	 imax;
    eint32_t	 mask;
    ecase_t	*cases[1];
};

/*
 * Prototypes
 */
extern void
elightning(efunction_t *function);

extern void
init_lightning(void);

extern void
finish_lightning(void);

extern void
esearch_instruction_pointer(void);

extern ebool_t
ejit_pointer_p(eobject_t value);

/*
 * Externs
 */
extern eobject_t	ethread_exit_code;

#endif /* _elightning_h */
